import java.util.BitSet;

import javax.crypto.Cipher;
import javax.crypto.SecretKey;

public class DesEncrypter {
    Cipher ecipher;
    Cipher dcipher;

    DesEncrypter(SecretKey key) {
        try {
            ecipher = Cipher.getInstance("DES");
            dcipher = Cipher.getInstance("DES");
            ecipher.init(Cipher.ENCRYPT_MODE, key);
            dcipher.init(Cipher.DECRYPT_MODE, key);

        } catch (Exception e) {
        }
    }

    public String encrypt(String str) {
        try {
        	byte [] plainbytearray = rad64ToByteArray(str);

            // Encrypt
            byte[] enc = ecipher.doFinal(plainbytearray);

            // Encode bytes to base64 to get a string
            return byteArrayToRad64(enc);
        } catch (Exception e) {
        }
        return null;
    }

    public String decrypt(String str) {
        try {
            // Decode rad64 to get bytes
            byte[] cipherbytearray = rad64ToByteArray(str);

            // Decrypt
            byte[] decryptedbytearray = dcipher.doFinal(cipherbytearray);

            // Decode to Rad64
            return byteArrayToRad64(decryptedbytearray);
        } catch (Exception e)
        {
        }
        return null;
    }
    
 // incoming is 10 char strings
	public static byte[] rad64ToByteArray(String str)
	{
		BitSet bits = new BitSet();
		int val = 0;
		for(int i = 0; i<10; i++)
		{
			char ch = str.charAt(i);
			if(ch >= 'A' && ch <= 'Z')
				val = ch - 'A';
			else if(ch >= 'a' && ch <= 'z')
				val = ch - 'a' + 26;
			else if(ch >= '0' && ch <= '9')
				val = ch - '0' + 52;
			else if(ch == '+')
				val = 62;
			else if(ch == '/')
				val = 63;
			else
			{
				System.out.println("Conversion error");
				System.exit(0);
			}
			for (int j=0; j<6; j++)
			{
				bits.set(6*i+j, val%2>0);
				val /= 2;
			}
		}
		return toByteArray(bits);
	}
	
	// incoming is 10 char strings
	public static String byteArrayToRad64(byte[] bin)
	{
		BitSet bits = fromByteArray(bin);
		String rad64 = "";
		int val = 0;
		String temp = "";
		for(int i = 0; i<10; i++)
		{
			temp = "";
			for(int j = 0; j<6; j++)
			{
				if(bits.get(6*i + j))
					temp += "1";
				else
					temp += "0";
			}
			val = Integer.parseInt(temp, 2);
			char ch = 0;
			if(val >= 0 && val <= 25)
				ch = (char) (val + 'A');
			else if(val >= 26 && val <= 51)
				ch = (char) (val + 'a' - 26);
			else if(val >= 52 && val <= 61)
				ch = (char) (val + '0' - 52);
			else if(val == 62)
				ch = '+';
			else if(val == 63)
				ch = '/';
			else
			{
				System.out.println("Conversion error");
				System.exit(0);
			}
			rad64 = rad64 + ch;
		}
		temp = "";
		for(int j = 0; j<4; j++)
		{
			if(bits.get(60 + j))
				temp += "1";
			else
				temp += "0";
		}
		temp += "00";
		val = Integer.parseInt(temp, 2);
		char ch = 0;
		if(val >= 0 && val <= 25)
			ch = (char) (val + 'A');
		else if(val >= 26 && val <= 51)
			ch = (char) (val + 'a' - 26);
		else if(val >= 52 && val <= 61)
			ch = (char) (val + '0' - 52);
		else if(val == 62)
			ch = '+';
		else if(val == 63)
			ch = '/';
		else
		{
			System.out.println("Conversion error");
			System.exit(0);
		}
		rad64 = rad64 + ch;
		return rad64;
	}
	// Returns a bitset containing the values in bytes.
	// The byte-ordering of bytes must be big-endian which means the most significant bit is in element 0.
	public static BitSet fromByteArray(byte[] bytes) {
	    BitSet bits = new BitSet();
	    for (int i=0; i<bytes.length*8; i++) {
	        if ((bytes[bytes.length-i/8-1]&(1<<(i%8))) > 0) {
	            bits.set(i);
	        }
	    }
	    return bits;
	}

	// Returns a byte array of at least length 1.
	// The most significant bit in the result is guaranteed not to be a 1
	// (since BitSet does not support sign extension).
	// The byte-ordering of the result is big-endian which means the most significant bit is in element 0.
	// The bit at index 0 of the bit set is assumed to be the least significant bit.
	public static byte[] toByteArray(BitSet bits) {
	    byte[] bytes = new byte[bits.length()/8+1];
	    for (int i=0; i<bits.length(); i++) {
	        if (bits.get(i)) {
	            bytes[bytes.length-i/8-1] |= 1<<(i%8);
	        }
	    }
	    return bytes;
	}

}
